package main

import (
	"fmt"
	"net"

	log "github.com/sirupsen/logrus"
)

// TCPConfig TCP config
type TCPConfig struct {
	IP   string `json:"ip,omitempty"`
	Port uint16 `json:"port,omitempty"`
	// AuxProperty map[string]interface{} `json:"auxProperty,omitempty"`
}

// TCPReceiver TCP receiver handle
type TCPReceiver struct {
	config     TCPConfig
	conn       *net.TCPListener
	handleConn func(conn net.Conn)
}

// Open open receiver
func (d *TCPReceiver) Open() error {
	bind := fmt.Sprintf("%s:%d", d.config.IP, d.config.Port)
	addr, err := net.ResolveTCPAddr("tcp", bind)
	if err != nil {
		return err
	}
	d.conn, err = net.ListenTCP("tcp", addr)
	if err != nil {
		return err
	}
	log.WithFields(log.Fields{"config": d.config}).Info("TCP listen open")
	// defer s4001.Close() // nolint
	return nil
}

// Start start the receiver
func (d *TCPReceiver) Start() error {
	log.Info("TCP listen start")
	go func() {
		for {
			conn, err := d.conn.Accept()
			if err != nil {
				log.WithFields(log.Fields{"err": err}).Error("error accept tcp connection")
				continue
			}
			log.WithFields(log.Fields{"conn": conn.RemoteAddr()}).Info("handle connection")
			go d.handleConn(conn)
		}
	}()
	return nil
}

// NewTCPReceiver create new receiver instance
func NewTCPReceiver(params TCPConfig, handler func(conn net.Conn)) (TCPReceiver, error) {
	d := TCPReceiver{
		config:     params,
		handleConn: handler,
	}
	return d, nil
}
